package com.jcfk.system.service;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jcfk.common.core.context.SpringContextUtils;
import com.jcfk.common.security.utils.SecurityUtils;
import com.jcfk.system.domain.model.SendMsgModel;
import com.jcfk.system.domain.po.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 消息发送服务
 */

@Component("sendMessageService")
@Transactional(rollbackFor = Exception.class)
public class SendMessageCenterService {

    @Autowired
    private SysMessageTypeService sysMessageTypeService;

    @Autowired
    private SysMessageSendRecordService sysMessageSendRecordService;


    ExecutorService executorService = Executors.newFixedThreadPool(10);

    public Map<String, List<String>> sendMessage(SendMsgModel sendMsgModel) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {

        sendMsgModel.setMsgTypeCodeList(sendMsgModel.getMsgTypeCodeList().stream().distinct().collect(Collectors.toList()));
        List<String> errCodes = new ArrayList<>();
        List<String> sueccesscodes = new ArrayList<>();
        if (sendMsgModel.getMsgTypeCodeList() != null && sendMsgModel.getMsgTypeCodeList().size() > 0) {
            for (String code : sendMsgModel.getMsgTypeCodeList()) {
                // 模板查询
                QueryWrapper<SysMessageType> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(SysMessageType::getTypeCode, code).eq(SysMessageType::getDeleted, 0).eq(SysMessageType::getEnabled, 1);
                SysMessageType sysMessageType = sysMessageTypeService.getOne(queryWrapper);


                // 不存在直接返回
                if (sysMessageType == null) {
                    errCodes.add(code);
                    continue;
                }
                sueccesscodes.add(code);

                sendMsgModel.setMessageLevel(sysMessageType.getMessageLevel());
                sendMsgModel.setMsgTypeId(sysMessageType.getId());
                if (sendMsgModel.getUrl() == null)
                    sendMsgModel.setUrl(sysMessageType.getUrl());

                for (String key : sendMsgModel.getContent().keySet()) {
                    Object value = sendMsgModel.getContent().get(key);
                    String replaceStr = "{" + key + "}";
                    sysMessageType.setContent(sysMessageType.getContent().replace(replaceStr, value.toString()));
                }

                SysMessageSendRecord record = new SysMessageSendRecord();
                record.setTitle(sendMsgModel.getTitle());
                record.setContent(sysMessageType.getContent());
                record.setTempleId(sysMessageType.getId());
                record.setSendTime(new Date());
                record.setMessageStatus(0);
                record.setCreatedUserId("1");
                record.setCreatedUserName("管理员");
                record.setCreateTime(new Date());
                record.setLastUpdatedUserId("1");
                record.setLastUpdateTime(new Date());
                sysMessageSendRecordService.save(record);

                sendMsgModel.setMsgBody(sysMessageType.getContent());

                Object[] params = new Object[]{sendMsgModel, record};

                Object target = SpringContextUtils.getBean(sysMessageType.getSendPackageName() + "Service");
                Method method = target.getClass().getDeclaredMethod(sysMessageType.getSendPackageName(),
                        SendMsgModel.class, SysMessageSendRecord.class);

                Callable<Object> callable = () -> {
                    // 在子线程中设置请求上下文对象
                    method.invoke(target, params);
                    return null;
                };

                executorService.submit(callable);
            }

        }
        Map<String, List<String>> map = new HashMap<>();
        map.put("errMsgTypeCodeList", errCodes);
        map.put("successMsgTypeCodeList", sueccesscodes);
        return map;
    }
}
